package com.tinify.loader;


import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashSet;
import java.util.Set;
import java.util.Stack;

public class RuntimeClassLoader {

    private final static Set<String> sClassPaths = new HashSet<>();

    public synchronized void loadClassFiles(String classpath) {
        File libfile = new File(classpath); // 从URLClassLoader类中获取类所在文件夹的方法，jar也可以认为是一个文件夹
        if (!libfile.exists()) {
            System.out.println("jar file not found.");
            return;
        }
        Stack<File> stack = new Stack<>();
        stack.push(libfile);

        do {
            if (stack.empty()) break;
            File pop = stack.pop();
            if (isJavaFile(pop)) {
                loadClassPathClasses(pop);
                System.out.println("load classpath : " + pop);
                continue;
            }
            File[] files = pop.listFiles();
            if (files == null) continue;
            for (File subFile : files) {
                stack.push(subFile);
            }

        } while (true);


    }

    private boolean isJavaFile(File pop) {
        if (!pop.isFile()) return false;
        String absolutePath = pop.getAbsolutePath();
        return absolutePath.endsWith(".jar") || absolutePath.endsWith(".class");
    }

    public synchronized void addClassPath(String classPath) {
        sClassPaths.add(classPath);
    }


    private static void loadClassPathClasses(File jarFile) {
        //获取类加载器的addURL方法，准备动态调用
        Method method = null;
        try {
            method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);
        } catch (NoSuchMethodException | SecurityException e1) {
            e1.printStackTrace();
        }
        // 获取方法的访问权限，保存原始值
        boolean accessible = method.isAccessible();
        try {
            //修改访问权限为可写
            if (accessible == false) {
                method.setAccessible(true);
            }
            // 获取系统类加载器
            URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
            //获取jar文件的url路径
            URL url = jarFile.toURI().toURL();
            //jar路径加入到系统url路径里
            method.invoke(classLoader, url);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //回写访问权限
            method.setAccessible(accessible);
        }
    }

    public void startLoadClasses() {
        if (sClassPaths.size() == 0) return;
        for (String classPath : sClassPaths) {
            if (classPath == null || classPath.length() == 0) continue;
            loadClassFiles(classPath);
        }

    }
}
